# -*- coding: utf-8 -*-
# @Time    : 2024/7/26 15:45
# @Author  : yujiahao
# @File    : 63_fastapi_dataclass.py
# @description:使用数据类


"""
路径操作函数的参数类型声明为 Request：

1. 将路径操作函数的参数类型声明为 Request，FastAPI 就能把 Request 传递到参数里。

2. 提取和验证路径参数：
   - 除了声明请求参数之外，还声明了路径参数。
   - 因此，能够提取、验证路径参数、并转换为指定类型，还可以用 OpenAPI 注释。

3. 声明其他参数：
   - 可以正常声明其他参数，同时提取 Request 对象。

4. 使用 Pydantic 及其内置的 dataclasses：
   - 即便上述代码没有显式使用 Pydantic，FastAPI 仍会使用 Pydantic 把标准数据类转换为 Pydantic 数据类（dataclasses）。
   - 它仍然支持以下功能：
     - 数据验证
     - 数据序列化
     - 数据存档等
   - 数据类的行为和运作方式与 Pydantic 模型相同。实际上，它的底层使用的也是 Pydantic。

说明：
- 注意，数据类不支持 Pydantic 模型的所有功能。
- 因此，开发时仍需要使用 Pydantic 模型。
- 但如果数据类很多，这一技巧能给 FastAPI 开发 Web API 增添不少助力。🤓
"""

from dataclasses import field  #
from typing import List, Union

from fastapi import FastAPI
from pydantic.dataclasses import dataclass  #


# FastAPI 基于 Pydantic 构建，前文已经介绍过如何使用 Pydantic 模型声明请求与响应。
# 但 FastAPI 还可以使用数据类（dataclasses）

# todo 普通用法
@dataclass
class Item:
    name: str
    price: float
    description: Union[str, None] = None
    tax: Union[float, None] = None


app = FastAPI()


@app.post("/items/")
async def create_item(item: Item):
    return item


# response_model 使用数据类
@app.get("/items/next", response_model=Item)
async def read_next_item():
    return {
        "name": "Island In The Moon",
        "price": 12.99,
        "description": "A place to be be playin' and havin' fun",
        "tags": ["breater"],
    }


# todo 在嵌套数据结构中使用数据类

# 还可以把 dataclasses 与其它类型注解组合在一起，创建嵌套数据结构。
# 还有一些情况也可以使用 Pydantic 的 dataclasses
# 把 dataclasses 与其它类型注解组合在一起，可以组成不同形式的复杂数据结构。
# 还可以把 dataclasses 与其它 Pydantic 模型组合在一起，继承合并的模型，把它们包含在您自己的模型里
@dataclass
class Item_2:
    name: str
    description: Union[str, None] = None


@dataclass
class Author:
    name: str
    items: List[Item_2] = field(default_factory=list)  #


app = FastAPI()


@app.post("/authors/{author_id}/items/", response_model=Author)  #
async def create_author_items(author_id: str, items: List[Item_2]):  #
    return {"name": author_id, "items": items}  #


@app.get("/authors/", response_model=List[Author])  #
def get_authors():  #
    return [  #
        {
            "name": "Breaters",
            "items": [
                {
                    "name": "Island In The Moon",
                    "description": "A place to be be playin' and havin' fun",
                },
                {"name": "Holy Buddies"},
            ],
        },
        {
            "name": "System of an Up",
            "items": [
                {
                    "name": "Salt",
                    "description": "The kombucha mushroom people's favorite",
                },
                {"name": "Pad Thai"},
                {
                    "name": "Lonely Night",
                    "description": "The mostests lonliest nightiest of allest",
                },
            ],
        },
    ]
